﻿using PBO.Network.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PBO.Network
{
    public class PokemonBattleClient : IBattleClientService
    {
        private ITopClient client;

        public PokemonBattleClient(string ip)
        {
            this.client = new BattleClient(ip, (int)ServerPort.PokemonBattleServerPort);
            this.client.ReceiveData += OnReceiveData;
        }

        public PokemonBattleClient(ITopClient client)
        {
            this.client = client;
            this.client.ReceiveData += OnReceiveData;
        }

        #region Events
        public event Action<PlayerMove> OnSetMove;
        public event Action<byte, string, List<byte>> OnSetTeam;
        public event Action<string> OnPlayerExit;
        public event Action<string, TieMessage> OnTie;
        public event Action<int> OnSetSeed;
        public event Action<List<BattleRule>> OnSetRules;

        public event Action<BattleInfo> OnSetBattleInfo;
        public event Action<BattleSnapshot> OnSetSnapshot;
        public event Action OnRegistObserver;

        public event Action OnLogoned;
        public event Action<string> OnLogonFailed;
        public event Action<string> OnPlayerTimeUp;
        #endregion

        #region Send

        public void SendMove(PlayerMove move)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_ReceiveMove_Hash, move);
        }

        public void SendTeam(byte position, string identity, List<byte> team)
        {
            var rsp = new UserInfo();
            rsp.position = position;
            rsp.identity = identity;
            rsp.team = team;
            client.SendData((int)EnumPokemonBattleMethods.Server_ReceiveTeam_Hash, rsp);
        }

        public void Exit(string identity)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_Exit_Hash, identity);
        }

        public void Tie(string identity, TieMessage message)
        {
            var rsp = new TieMessageResponse();
            rsp.identity = identity;
            rsp.message = message;
            client.SendData((int)EnumPokemonBattleMethods.Server_ReceiveTieMessage_Hash, rsp);
        }

        public void Logon(string identity, BattleMode mode, string versionInfo)
        {
            var rsp = new LogonResponse();
            rsp.identity = identity;
            rsp.modeInfo = mode;
            rsp.versionInfo = versionInfo;
            client.SendData((int)EnumPokemonBattleMethods.Server_Logon_Hash, rsp);
        }

        public void RegistObserver(int identity)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_RegistObsever_Hash, identity);
        }

        public void SendBattleInfo(BattleInfo info)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_ReceiveBattleInfo_Hash, info);
        }

        public void SendBattleSnapshot(BattleSnapshot snapshot)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_ReceiveBattleSnapshot_Hash, snapshot);
        }

        public void TimeUp(string identity)
        {
            client.SendData((int)EnumPokemonBattleMethods.Server_TimeUp_Hash, identity);
        }

        #endregion

        #region event

        protected void OnLogonSuccess()
        {
            if (OnLogoned != null) OnLogoned();
        }

        protected void OnLogonFail(string message)
        {
            if (OnLogonFailed != null) OnLogonFailed(message);
        }

        protected void OnReceiveRandomSeed(int seed)
        {
            if (OnSetSeed != null) OnSetSeed(seed);
        }

        protected void OnReceiveMove(PlayerMove move)
        {
            if (OnSetMove != null) OnSetMove(move);
        }

        protected void OnReceiveTeam(UserInfo rsp)
        {
            if (OnSetTeam != null) OnSetTeam(rsp.position, rsp.identity, rsp.team);
        }

        protected void OnReceiveRules(List<BattleRule> rules)
        {
            if (OnSetRules != null) OnSetRules(rules);
        }

        protected void OnExit(string identity)
        {
            if (OnPlayerExit != null) OnPlayerExit(identity);
        }

        protected void OnReceiveTieMessage(TieMessageResponse rsp)
        {
            if (OnTie != null) OnTie(rsp.identity, rsp.message);
        }

        protected void OnRegistObsever(int identity)
        {
            if (OnRegistObserver != null) OnRegistObserver();
        }

        protected void OnReceiveBattleInfo(BattleInfo info)
        {
            if (OnSetBattleInfo != null) OnSetBattleInfo(info);
        }

        protected void OnReceiveBattleSnapshot(BattleSnapshot snapshot)
        {
            if (OnSetSnapshot != null) OnSetSnapshot(snapshot);
        }

        protected void OnTimeUp(string identity)
        {
            if (OnPlayerTimeUp != null) OnPlayerTimeUp(identity);
        }
        #endregion

        protected virtual void OnReceiveData(int sessionID, int method, string json)
        {
            switch ((EnumPokemonBattleMethods)method)
            {
                case EnumPokemonBattleMethods.Client_LogonSuccess_Hash:
                    OnLogonSuccess();
                    break;
                case EnumPokemonBattleMethods.Client_LogonFail_Hash:
                    OnLogonFail(json);
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveRandomSeed_Hash:
                    OnReceiveRandomSeed(int.Parse(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveMove_Hash:
                    OnReceiveMove(StringUtils.ParseResponse<PlayerMove>(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveTeam_Hash:
                    OnReceiveTeam(StringUtils.ParseResponse<UserInfo>(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveRules_Hash:
                    OnReceiveRules(StringUtils.ParseResponse<List<BattleRule>>(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveTieMessage_Hash:
                    OnReceiveTieMessage(StringUtils.ParseResponse<TieMessageResponse>(json));
                    break;
                case EnumPokemonBattleMethods.Client_Exit_Hash:
                    OnExit(json);
                    break;
                case EnumPokemonBattleMethods.Client_TimeUp_Hash:
                    OnTimeUp(json);
                    break;
                case EnumPokemonBattleMethods.Client_RegistObsever_Hash:
                    OnRegistObsever(int.Parse(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveBattleInfo_Hash:
                    OnReceiveBattleInfo(StringUtils.ParseResponse<BattleInfo>(json));
                    break;
                case EnumPokemonBattleMethods.Client_ReceiveBattleSnapshot_Hash:
                    OnReceiveBattleSnapshot(StringUtils.ParseResponse<BattleSnapshot>(json));
                    break;
            }
        }
    }
}
